﻿using System;
using System.Collections.Generic;
using System.Data;

namespace BLL
{
    public abstract class EntityBLL<TEntity> : BaseBLL where TEntity : class, new()
    {
        public virtual bool Insert(TEntity entity)
        {
            var type = typeof(TEntity);
            var TableColums = type.GetProperties();
            //自动拼接SQL
            var sql = "INSERT INTO " + type.Name + "({0}) VALUES({1})";
            var prames = "";
            var pramesv = "";

            for (int i = 0; i < TableColums.Length; i++)
            {
                prames += TableColums[i].Name;
                bool k = false;
                if (TableColums[i].PropertyType == typeof(DateTime))
                {
                    pramesv += "TO_DATE('" + ((DateTime)TableColums[i].GetValue(entity, null)).ToString("yyyy-MM-dd HH:mm:ss") + "','YYYY-MM-DD HH24:MI:SS')";
                    k = true;
                }
                if (TableColums[i].PropertyType == typeof(decimal) && k == false)
                {
                    pramesv += TableColums[i].GetValue(entity, null).ToString();
                    k = true;
                }
                if (k == false)
                {
                    pramesv += "'" + TableColums[i].GetValue(entity, null).ToString() + "'";
                }
                if (i + 1 != TableColums.Length)
                {
                    prames += ",";
                    pramesv += ",";
                }
            }
            sql = string.Format(sql, prames, pramesv);
            return NoQuery(sql) > 0 ? true : false;
        }

        public abstract bool Update(TEntity entity);

        public abstract TEntity Find(object key);

        public virtual List<TEntity> Where(string whereStr = null, string orderbyStr = null, int? skip = null, int? take = null)
        {
            var sql = "SELECT * FROM " + (typeof(TEntity)).Name;
            if (whereStr != null)
            {
                sql += " WHERE " + whereStr;
            }
            if (orderbyStr != null)
            {
                sql += " ORDER BY " + orderbyStr;
            }
            var dt = PageQuery(sql, skip, take);
            return ConvertEntity(dt);
        }

        public virtual List<TEntity> ConvertEntity(DataTable _table)
        {
            var TableColums = (typeof(TEntity)).GetProperties();
            List<TEntity> entitys = new List<TEntity>();

            if (_table != null)
            {
                DataTable table = _table.Copy();
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    table.Columns[i].ColumnName = table.Columns[i].ColumnName.ToUpper();
                }

                foreach (DataRow item in table.Rows)
                {
                    var entity = new TEntity();
                    foreach (var itm in TableColums)
                    {
                        if (table.Columns.Contains(itm.Name.ToUpper()))
                        {
                            var value = item[itm.Name.ToUpper()];
                            if (value != DBNull.Value)
                            {
                                itm.SetValue(entity, ConvertTo(value, itm.PropertyType), null);
                            }
                        }
                    }
                    entitys.Add(entity);
                }
            }

            return entitys;
        }

        public static object ConvertTo(object convertibleValue, Type type)
        {
            if (!type.IsGenericType)
            {
                return Convert.ChangeType(convertibleValue, type);
            }
            else
            {
                Type genericTypeDefinition = type.GetGenericTypeDefinition();
                if (genericTypeDefinition == typeof(Nullable<>))
                {
                    return Convert.ChangeType(convertibleValue, Nullable.GetUnderlyingType(type));
                }
            }
            throw new InvalidCastException(string.Format("Invalid cast from type \"{0}\" to type \"{1}\".", convertibleValue.GetType().FullName, type.FullName));
        }
    }
}